package cn.itcast.wanxinp2p.consumer.service.impl;

import cn.itcast.wanxinp2p.api.account.model.AccountDTO;
import cn.itcast.wanxinp2p.api.account.model.AccountRegisterDTO;
import cn.itcast.wanxinp2p.api.consumer.model.BankCardDTO;
import cn.itcast.wanxinp2p.api.consumer.model.ConsumerDTO;
import cn.itcast.wanxinp2p.api.consumer.model.ConsumerRegisterDTO;
import cn.itcast.wanxinp2p.api.consumer.model.ConsumerRequest;
import cn.itcast.wanxinp2p.api.depository.model.GatewayRequest;
import cn.itcast.wanxinp2p.common.domain.*;
import cn.itcast.wanxinp2p.common.util.CodeNoUtil;
import cn.itcast.wanxinp2p.consumer.agent.AccountAPIAgent;
import cn.itcast.wanxinp2p.consumer.agent.DepositoryAgentApiAgent;
import cn.itcast.wanxinp2p.consumer.common.ConsumerErrorCode;
import cn.itcast.wanxinp2p.consumer.entity.BankCard;
import cn.itcast.wanxinp2p.consumer.entity.Consumer;
import cn.itcast.wanxinp2p.consumer.mapper.ConsumerMapper;
import cn.itcast.wanxinp2p.consumer.service.BankCardService;
import cn.itcast.wanxinp2p.consumer.service.ConsumerService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.Hmily;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
public class ConsumerServiceImpl extends ServiceImpl<ConsumerMapper, Consumer> implements ConsumerService {

    @Autowired
    private ConsumerMapper consumerMapper;
    @Autowired
    private AccountAPIAgent accountAPIAgent;
    @Autowired
    private BankCardService bankCardService;
    @Autowired
    private DepositoryAgentApiAgent depositoryAgentApiAgent;

    @Override
    public Integer checkMobile(String mobile) {
        return getByMobile(mobile) != null?1:0;
    }

    /**
     * 根据手机号查询用户信息
     * @param mobile
     * @return
     */
    private ConsumerDTO getByMobile(String mobile){
        Consumer consumer = consumerMapper.selectOne(new LambdaQueryWrapper<Consumer>().eq(Consumer::getMobile, mobile));
        if(consumer == null) return null;
        ConsumerDTO consumerDTO = new ConsumerDTO();
        BeanUtils.copyProperties(consumer,consumerDTO);
        return consumerDTO;
    }

    @Override
    @Hmily(confirmMethod = "confirmRegister", cancelMethod = "cancelRegister")
    public void register(ConsumerRegisterDTO consumerRegisterDTO) {
        //数据库如果可以查到这个手机号的用户就报错用户已存在，不能注册
        if(checkMobile(consumerRegisterDTO.getMobile()) == 1){
            throw new BusinessException(ConsumerErrorCode.E_140107);
        }
        Consumer consumer = new Consumer();
        BeanUtils.copyProperties(consumerRegisterDTO,consumer);
        consumer.setUsername(CodeNoUtil.getNo(CodePrefixCode.CODE_NO_PREFIX));
        consumerRegisterDTO.setUsername(consumer.getUsername());
        consumer.setUserNo(CodeNoUtil.getNo(CodePrefixCode.CODE_REQUEST_PREFIX));
        consumer.setIsBindCard(0);
        consumerMapper.insert(consumer);
        AccountRegisterDTO accountRegisterDTO = new AccountRegisterDTO();
        BeanUtils.copyProperties(consumerRegisterDTO,accountRegisterDTO);
        RestResponse<AccountDTO> response = accountAPIAgent.register(accountRegisterDTO);
        if(response.getCode() != CommonErrorCode.SUCCESS.getCode()){
            throw new BusinessException(ConsumerErrorCode.E_140106);
        }
    }

    public void confirmRegister(ConsumerRegisterDTO consumerRegisterDTO) {
        log.info("Try没问题，执行Confirm");
    }

    public void cancelRegister(ConsumerRegisterDTO consumerRegisterDTO) {
        log.info("Try有问题，执行Cancel");
        remove(Wrappers.<Consumer>lambdaQuery().eq(Consumer::getMobile, consumerRegisterDTO.getMobile()));
    }

    @Override
    @Transactional
    public RestResponse<GatewayRequest> createConsumer(ConsumerRequest consumerRequest) {
        //1.判断用户是否已经开户
        Consumer consumer = consumerMapper.selectOne(new LambdaQueryWrapper<Consumer>().eq(Consumer::getMobile, consumerRequest.getMobile()));
        if(consumer.getIsBindCard() == 1){
            throw new BusinessException(ConsumerErrorCode.E_140105);
        }
        //2.判断提交过来的银行卡是否已被绑定
        BankCardDTO bankCardDTO = bankCardService.getByCardNumber(consumerRequest.getCardNumber());
        if(bankCardDTO != null && bankCardDTO.getStatus() == StatusCode.STATUS_IN.getCode()){
            throw new BusinessException(ConsumerErrorCode.E_140151);
        }
        //3.更新用户的信息
        consumerRequest.setId(consumer.getId());
        consumerRequest.setUserNo(CodeNoUtil.getNo(CodePrefixCode.CODE_CONSUMER_PREFIX));
        consumerRequest.setRequestNo(CodeNoUtil.getNo(CodePrefixCode.CODE_REQUEST_PREFIX));
        LambdaUpdateWrapper<Consumer> eq = new LambdaUpdateWrapper<Consumer>()
                .set(Consumer::getFullname, consumerRequest.getFullname())
                .set(Consumer::getUserNo, consumerRequest.getUserNo())
                .set(Consumer::getRequestNo, consumerRequest.getRequestNo())
                .set(Consumer::getIdNumber, consumerRequest.getIdNumber())
                .set(Consumer::getAuthList, "ALL")
                .eq(Consumer::getMobile, consumerRequest.getMobile());
        update(eq);
        //4.保存银行卡信息
        BankCard bankCard = new BankCard();
        bankCard.setConsumerId(consumer.getId());
        bankCard.setBankCode(consumerRequest.getBankCode());
        bankCard.setCardNumber(consumerRequest.getCardNumber());
        bankCard.setMobile(consumerRequest.getMobile());
        bankCard.setStatus(StatusCode.STATUS_OUT.getCode());
        BankCardDTO dto = bankCardService.getByConsumerId(consumer.getId());
        if(dto != null){
            //如果能查到银行卡的信息，则修改银行卡信息，否则就走新增
            bankCard.setId(dto.getId());
        }
        bankCardService.saveOrUpdate(bankCard);
        //5.准备数据，发起远程调用，把数据发到存管代理服务
        return depositoryAgentApiAgent.createConsumer(consumerRequest);
    }
}
